/* $Id$ */
/* vim: set filetype=verilog ts=8 sw=4 tw=132: */
/*****************************************************************************
 
              (c) Copyright 1987 - 2012,  VIA Technologies, Inc.       
                            ALL RIGHTS RESERVED                            
                                                                     
 This design and all of its related documentation constitutes valuable and
 confidential property of VIA Technologies, Inc.  No part of it may be
 reproduced in any form or by any means   used to make any transformation
 / adaptation / redistribution without the prior written permission from the
 copyright holders. 
 
------------------------------------------------------------------------------

  DESCRIPTION:

  FEATURES:

  TODO:

  AUTHORS:
     Shawn Fang
    
------------------------------------------------------------------------------
                             REVISION HISTORY
    $Log$

*****************************************************************************/
module memory(
	/*
    //outputs
    output [31:0] valM,
    output reg  [31:0] maddr,
    output wenable,
    output reg  [31:0] wdata,
    output renable,
    output reg   [2:0] stat,
    //inputs
    input  clock,
    input  reset,
    input  [3:0] icode,
    input  [3:0] ifun,
    input  [31:0] valE,
    input  [31:0] valA,
    input  [31:0] valP,
    input  [31:0] rdata,
    input  m_ok,
    input  i_ok,
    input  instrErr
    */
   // Outputs
                     output reg[31:0] maddr ,//            (maddr[31:0]),
                     output wenable      , //    (wenable),
                      output [31:0] wdata  , //          (wdata[31:0]),
                     output renable      , //    (renable),
                     output [3:0] m_icode   ,//        (m_icode[2:0]),
                      output [31:0] m_valM  , //         (m_valM[31:0]),
                      output [31:0] m_valE   , //        (m_valE[31:0]),
                      output [31:0] m_valA   , //        (m_valA[31:0]),
                      output [3:0] m_dstM     ,//       (m_dstM[3:0]),
                      output [3:0] m_dstE     ,//       (m_dstE[3:0]),
                      output reg    [2:0] m_stat     ,//       (m_stat[2:0]),
                      output reg    m_cnd           ,//  (m_cnd),
                     // Inputs
                     input  clock,//             (clock),
                     input  reset ,//            (reset),
                     input  [3:0] e_icode ,//          (e_icode[3:0]),
                     input  [31:0] e_valE  ,//          (e_valE[31:0]),
                     input  [31:0] e_valA  ,//           (e_valA[31:0]),
                     input  [3:0] e_dstE  ,//          (e_dstE[3:0]),
                     input  [3:0] e_dstM  ,//          (e_dstM[3:0]),
                     input  [2:0] e_stat  ,//          
		     input  e_cnd,
                     input  [31:0] rdata   ,//          (rdata[31:0]),
                     input  m_ok    ,//          (m_ok))
		     input  M_stall,
		     input  M_bubble
    );

    assign renable=(m_icode==`IMRMOVL
		    ||m_icode==`IPOPL
		    ||m_icode==`IRET)?1'b1:1'b0;
    //always @ (i_ok or m_ok or icode)
    /*
    always @ (posedge clock or posedge reset)
    begin
	if(reset)
	    m_stat<=`SAOK;
	else
	begin
	    if(~i_ok || ~m_ok)
		m_stat<=`SADR;
	    else if(instrErr)
		m_stat<=`SINS;
	    else if(icode==`IHALT)
		m_stat<=`SHLT;
	    else
		m_stat<=`SAOK;
	end
    end
    */
    always @ (posedge clock or posedge reset)
    begin
	if(reset)
	    m_stat<=`SAOK;
	else
	begin
	    if(M_stall)
		m_stat<=m_stat;
	    else if(M_bubble)
		m_stat<=`SAOK;
	    else if(e_stat==`SAOK)
	    begin
		if(~m_ok)
			m_stat<=`SADR;
		// else if(m_icode==`IHALT)
		//	m_stat<=`SHLT;
		 else
			m_stat<=`SAOK;
	    end
	    else
		m_stat<=e_stat;
	    
	end
    end
    always @ (posedge clock or posedge reset)
    begin
	if(reset)
	    m_cnd<=1;
	else
	begin
	    if(M_stall)
		m_cnd<=m_cnd;
	    else if(M_bubble)
		m_cnd<=1;
	    else 
		m_cnd<=e_cnd;
	end
    end

    always @ (m_icode or m_valE or m_valA)
    begin
	if(m_icode==`IRMMOVL
	    ||m_icode==`IPUSHL
	    ||m_icode==`ICALL
	    ||m_icode==`IMRMOVL)
	    maddr<=m_valE;
	else if(m_icode==`IPOPL||m_icode==`IRET)
	    maddr<=m_valA;
	else
	    maddr<=0;
    end

    assign m_valM=rdata;
    assign renable=(m_icode== `IMRMOVL
		    || m_icode==`IPOPL
		    || m_icode==`IRET)?1'b1:1'b0;
    assign wenable=(m_icode==`IRMMOVL
		    ||m_icode==`IPUSHL
		    ||m_icode==`ICALL)?1'b1:1'b0;

    assign wdata=m_valA;

ppregs_M U_ppregs_M
    (
	.clock(clock),
	.reset(reset),
	.M_stall(M_stall),
        .M_bubble(M_bubble),
	.icode_i(e_icode),
	.dstE_i(e_dstE),
	.dstM_i(e_dstM),
	.valE_i(e_valE),
	.valA_i(e_valA),

	.icode_o(m_icode),
	.dstE_o(m_dstE),
	.dstM_o(m_dstM),
	.valA_o(m_valA),
	.valE_o(m_valE)
	    );

endmodule
